from rest_framework import viewsets, status
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.response import Response
from rest_framework.decorators import action  # 必须导入action装饰器
from django.http import FileResponse  # 用于文件响应（预览/下载）
from django.shortcuts import render, redirect
from django.urls import reverse

from .models import File
from .serializers import FileSerializer
from .forms import FileUploadForm


class FileViewSet(viewsets.ModelViewSet):
    serializer_class = FileSerializer
    permission_classes = [IsAuthenticated]
    queryset = File.objects.all()

    # 已有的方法（保持不变）
    def get_queryset(self):
        user = self.request.user
        if user.role == 'admin':
            return File.objects.all()
        elif user.role == 'reviewer':
            return File.objects.all()
        else:
            return File.objects.filter(uploaded_by=user)

    def perform_create(self, serializer):
        serializer.save(uploaded_by=self.request.user)

    def get_permissions(self):
        if self.action in ['list', 'retrieve']:
            return [IsAuthenticated()]
        elif self.action == 'create':
            return [IsAuthenticated()]
        elif self.action in ['update', 'partial_update', 'destroy']:
            return [IsAdminUser()]
        return []

    # 下载功能（已有的自定义动作）
    @action(detail=True, methods=['get'])
    def download(self, request, pk=None):
        file_obj = self.get_object()
        if request.user.role not in ['admin', 'reviewer'] and file_obj.uploaded_by != request.user:
            return Response({'error': '没有下载权限'}, status=status.HTTP_403_FORBIDDEN)
        try:
            with open(file_obj.file.path, 'rb') as f:
                response = FileResponse(f)
                response['Content-Disposition'] = f'attachment; filename="{file_obj.name}"'
                return response
        except FileNotFoundError:
            return Response({'error': '文件不存在'}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({'error': f'下载失败：{str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    # 预览功能（新增的自定义动作，放在这里！）
    @action(detail=True, methods=['get'])
    def preview(self, request, pk=None):
        file_obj = self.get_object()  # 获取当前文件对象

        # 1. 权限验证（与下载保持一致，避免未授权预览）
        if request.user.role not in ['admin', 'reviewer'] and file_obj.uploaded_by != request.user:
            return Response({'error': '没有预览权限'}, status=status.HTTP_403_FORBIDDEN)

        # 2. 限制可预览的文件格式（图片和文本）
        allowed_extensions = ('.png', '.jpg', '.jpeg', '.txt')  # 扩展支持jpeg
        if not file_obj.file.name.lower().endswith(allowed_extensions):  # 忽略大小写（如.PNG）
            return Response(
                {'error': '不支持的预览格式，仅支持PNG、JPG、TXT'},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 3. 读取文件并返回预览响应（浏览器会自动渲染）
        try:
            with open(file_obj.file.path, 'rb') as f:
                response = FileResponse(f)
                # 可选：根据文件类型设置Content-Type（浏览器会更准确识别）
                if file_obj.file.name.lower().endswith(('.png', '.jpg', '.jpeg')):
                    response['Content-Type'] = 'image/jpeg' if file_obj.file.name.lower().endswith(
                        ('.jpg', '.jpeg')) else 'image/png'
                elif file_obj.file.name.lower().endswith('.txt'):
                    response['Content-Type'] = 'text/plain; charset=utf-8'  # 文本文件指定编码
                return response
        except FileNotFoundError:
            return Response({'error': '文件不存在'}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({'error': f'预览失败：{str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


# 上传视图（保持不变）
def upload_file_view(request):
    if not request.user.is_authenticated:
        return redirect(reverse('login'))
    if request.method == 'POST':
        form = FileUploadForm(request.POST, request.FILES)
        if form.is_valid():
            file_instance = form.save(commit=False)
            file_instance.uploaded_by = request.user
            file_instance.save()
            return redirect(reverse('file-list'))
    else:
        form = FileUploadForm()
    return render(request, 'upload.html', {'form': form})